#include "gamewindow.h"

#include "ui_gamewindow.h"

const int kBoardMargin = 30;  // 棋盘边缘空隙
const int kRadius = 15;       // 棋子半径
const int kBlockSize = 40;    // 格子的大小
const int kMarkSize = 6;      // 落子标记边长
const int kPosDelta = 20;     // 鼠标点击的模糊距离上限

extern int lastx, lasty;  // 上一步位置

int test = 0;

GameWindow::GameWindow(QWidget *parent) : QWidget(parent),
                                          ui(new Ui::GameWindow) {
    ui->setupUi(this);
}

GameWindow::~GameWindow() {
    emit showMain();
    delete ui;
    delete game;
}

GameWindow::GameWindow(int gameType, int difficulty, int order) : ui(new Ui::GameWindow) {
    ui->setupUi(this);
    over = 0;
    once = 0;
    recapMode = 0;

    setFixedSize(kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) + 100, kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1));

    returnBtn = new QPushButton(this);
    returnBtn->resize(120, 30);
    returnBtn->setText("返回主界面");
    returnBtn->move(kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 30, kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 100);

    withdrawBtn = new QPushButton(this);
    withdrawBtn->resize(120, 30);
    withdrawBtn->setText("悔棋");
    withdrawBtn->move(kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 30, kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 150);
    connect(withdrawBtn, &QPushButton::clicked, this, &GameWindow::withdraw);

    QFont f("Courier", 20, 0, false);

    now = new QLabel(this);
    now->resize(150, 50);
    now->setFont(f);
    now->setText("现在轮到：");
    now->move(kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 10, kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 500);

    whichPlayer = new QLabel(this);
    whichPlayer->resize(150, 50);
    whichPlayer->setFont(f);
    whichPlayer->setText("黑棋");
    whichPlayer->move(kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) + 9, kBoardMargin * 2 + kBlockSize * (kBoardSizeNum - 1) - 470);

    //    QLabel *label_pic = new QLabel(this);
    //    QPixmap pix(":/img/chess_board.png");
    //    label_pic->setGeometry(kBoardMargin + kBlockSize - 5, kBoardMargin - 5, 400, 400);
    //    label_pic->lower();
    //    int w = label_pic->width();
    //    int h = label_pic->height();
    //    label_pic->setPixmap(pix.scaled(w, h));

    setMouseTracking(true);  // 设置鼠标追踪
    finalDlg = new FinalDlg(this);
    connect(this, &GameWindow::setBlack, finalDlg, &FinalDlg::showBlack);
    connect(this, &GameWindow::setWhite, finalDlg, &FinalDlg::showWhite);
    this->show();
    connect(finalDlg, &FinalDlg::showHistory, this, &GameWindow::paintHistory);
    Board *board = new Board;
    game = new Game(board);

    if (order == 0) {
        game->setDifficulty(difficulty);
        game->setPlayer(0, 0, order);
        game->setPlayer(1, gameType, order);
    } else {
        game->setDifficulty(difficulty);
        game->setPlayer(0, gameType, order);
        game->setPlayer(1, 0, order);
    }
}

void GameWindow::paintHistory() {
    finalDlg->close();
    this->show();
    recapMode = 1;
};

void GameWindow::paintEvent(QPaintEvent *) {
    QPainter *painter = new QPainter(this);

    QPixmap pix;
    painter->translate(0, 0);
    pix.load(":/img/chess_board.png");                  // 加载图片地址 可以是资源文件
    painter->drawPixmap(0, 0, width(), height(), pix);  // 绘制图片 横坐标、纵坐标、宽度、高度

    // 绘制棋盘
    painter->setRenderHint(QPainter::Antialiasing, true);  // 抗锯齿
    for (int i = 0; i < kBoardSizeNum; ++i) {
        painter->drawLine(kBoardMargin + kBlockSize * i, kBoardMargin, kBoardMargin + kBlockSize * i, size().height() - kBoardMargin);
        painter->drawLine(kBoardMargin, kBoardMargin + kBlockSize * i, size().width() - kBoardMargin - 100, kBoardMargin + kBlockSize * i);
    }
    QBrush brush;
    brush.setStyle(Qt::SolidPattern);

    // 绘制落点预测
    if (clickPosRow >= 0 && clickPosRow < kBoardSizeNum &&
        clickPosCol >= 0 && clickPosCol < kBoardSizeNum &&
        game->getStatus(clickPosRow, clickPosCol) == 0) {
        if (game->getPlayer()->getColor() == -1)
            brush.setColor(Qt::white);
        else
            brush.setColor(Qt::black);
        painter->setBrush(brush);
        painter->drawRect(kBoardMargin + kBlockSize * clickPosCol - kMarkSize / 2, kBoardMargin + kBlockSize * clickPosRow - kMarkSize / 2, kMarkSize, kMarkSize);
    }

    // 绘制棋子
    int i = 0;
    for (auto p : game->history) {
        int x = p.first;
        int y = p.second;
        i++;

        if (game->getStatus(x, y) == 1)  // 绘制黑棋
        {
            brush.setColor(Qt::black);
            painter->setBrush(brush);
            painter->drawEllipse(kBoardMargin + kBlockSize * y - kRadius, kBoardMargin + kBlockSize * x - kRadius, kRadius * 2, kRadius * 2);
            if (recapMode == 1)  // 绘制数字
            {
                painter->setPen(Qt::white);
                painter->drawText(kBoardMargin + kBlockSize * y - kRadius + 11, kBoardMargin + kBlockSize * x - kRadius + 19, QString::number(i));
            }
        } else if (game->getStatus(x, y) == -1)  //绘制白棋
        {
            brush.setColor(Qt::white);
            painter->setBrush(brush);
            painter->drawEllipse(kBoardMargin + kBlockSize * y - kRadius, kBoardMargin + kBlockSize * x - kRadius, kRadius * 2, kRadius * 2);
            if (recapMode == 1)  // 绘制数字
            {
                painter->setPen(Qt::black);
                painter->drawText(kBoardMargin + kBlockSize * y - kRadius + 11, kBoardMargin + kBlockSize * x - kRadius + 19, QString::number(i));
            }
        }
        if (lastx == x && lasty == y && recapMode == 0)  // 绘制红点
        {
            brush.setColor(Qt::red);
            painter->setBrush(brush);
            painter->drawEllipse(kBoardMargin + kBlockSize * y - kRadius / 5, kBoardMargin + kBlockSize * x - kRadius / 5, kRadius * 2 / 5, kRadius * 2 / 5);
        }
    }

    // 只进行一次获胜
    if (once == 0) {
        switch (over) {
            case 0:
                break;
            case 1:
                blackWin();
                break;
            case -1:
                whiteWin();
                break;
            default:
                break;
        }
    }

    painter->end();
}

void GameWindow::mouseMoveEvent(QMouseEvent *event) {
    if (over != 0)
        event->ignore();
    // 获取鼠标当前的坐标
    int x = event->x();
    int y = event->y();

    if (x >= kBoardMargin - kBlockSize / 2 &&
        x < size().width() - kBoardMargin &&
        y >= kBoardMargin - kBlockSize / 2 &&
        y < size().height() - kBoardMargin) {
        // 获取最近的左上角的点
        int col = x / kBlockSize;
        int row = y / kBlockSize;

        int leftTopPosX = kBoardMargin + kBlockSize * col;
        int leftTopPosY = kBoardMargin + kBlockSize * row;

        // 根据距离算出合适的点击位置,一共四个点，根据半径距离选最近的
        clickPosRow = -1;  // 初始化最终的位置
        clickPosCol = -1;
        int len = 0;  // 计算完后取整就可以了

        // 确定一个误差在范围内最近的交叉点
        len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < kPosDelta) {
            clickPosRow = row;
            clickPosCol = col;
        }
        len = sqrt((x - leftTopPosX - kBlockSize) * (x - leftTopPosX - kBlockSize) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < kPosDelta) {
            clickPosRow = row;
            clickPosCol = col + 1;
        }
        len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY - kBlockSize) * (y - leftTopPosY - kBlockSize));
        if (len < kPosDelta) {
            clickPosRow = row + 1;
            clickPosCol = col;
        }
        len = sqrt((x - leftTopPosX - kBlockSize) * (x - leftTopPosX - kBlockSize) + (y - leftTopPosY - kBlockSize) * (y - leftTopPosY - kBlockSize));
        if (len < kPosDelta) {
            clickPosRow = row + 1;
            clickPosCol = col + 1;
        }
    }
    // 重新绘制棋盘
    update();

    //判断胜负
}

void GameWindow::mouseReleaseEvent(QMouseEvent *event) {
    // 游戏结束后禁用事件
    if (over != 0) {
        event->ignore();
        return;
    }

    if (game->getPlayer()->getType() == 0)  // 如果当前是人在下棋的话
    {
        chessOneByPerson();
        QSound::play(":/audio/place_chess.wav");
        flipPlayer();
    }

    if (over == 0) {
        if (game->getPlayer()->getType() == 1)  // 如果轮到AI下棋的话
        {
            chessOneByAi();
            QSound::play(":/audio/place_chess.wav");
            flipPlayer();
        }
    }
}

void GameWindow::chessOneByPerson() {
    // 根据当前存储的坐标下子
    // 只有有效点击才下子，并且该处没有子
    if (clickPosRow != -1 && clickPosCol != -1 && clickPosRow < kBoardSizeNum && clickPosCol < kBoardSizeNum && game->getStatus(clickPosRow, clickPosCol) == 0) {
        game->setStatus(clickPosRow, clickPosCol, game->getPlayer()->getColor());
        // 重绘
        update();
    }
    if (over == 0)
        over = game->rule(clickPosRow, clickPosCol);
    test++;
}

void GameWindow::chessOneByAi() {
    setMouseTracking(false);
    std::pair<int, int> t = game->getPlayer()->aiPick();
    game->setStatus(t.first, t.second, game->getPlayer()->getColor());
    over = game->rule(lastx, lasty);
    test++;
    setMouseTracking(true);
    update();
}

void GameWindow::blackWin() {
    if (once == 0) {
        once++;
        emit setBlack();
        finalDlg->setModal(true);
        finalDlg->exec();
    }
}

void GameWindow::whiteWin() {
    if (once == 0) {
        once++;
        emit setWhite();
        finalDlg->setModal(true);
        finalDlg->exec();
    }
}

// 显示下一步轮到谁
void GameWindow::flipPlayer() {
    if (game->getPlayer()->getColor() == 1)
        whichPlayer->setText("黑棋");
    else
        whichPlayer->setText("白棋");
}

// 悔棋
void GameWindow::withdraw() {
    int x, y;

    if (!game->history.empty()) {
        x = game->history.back().first;
        y = game->history.back().second;
        game->history.pop_back();
        game->setStatus(x, y, 0);
    }

    if (!game->history.empty()) {
        x = game->history.back().first;
        y = game->history.back().second;
        game->history.pop_back();
        game->setStatus(x, y, 0);
    }
    repaint();
}
